package com.cug.campus_sh_market_server.controller

import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
import com.cug.campus_sh_market_server.common.constant.UrlConstants.FILE_PREFIX
import com.cug.campus_sh_market_server.config.aop.ValidateAspect
import com.cug.campus_sh_market_server.entity.myenum.IsDelEnum
import com.cug.campus_sh_market_server.entity.po.File
import com.cug.campus_sh_market_server.entity.vo.ResultData
import com.cug.campus_sh_market_server.service.FileService
import com.cug.campus_sh_market_server.util.COSUtil
import com.cug.campus_sh_market_server.util.MappingUtil
import com.cug.campus_sh_market_server.util.MultipartFileToFile
import com.cug.campus_sh_market_server.util.UUIDUtils
import com.nycreativity.elecreativity.entity.param.file.FileQueryParam
import com.nycreativity.elecreativity.entity.param.file.FileUploadParam
import com.nycreativity.elecreativity.entity.vo.PageDataVO
import com.nycreativity.elecreativity.entity.vo.file.FileVO
import io.swagger.annotations.Api
import io.swagger.annotations.ApiImplicitParam
import io.swagger.annotations.ApiOperation
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.validation.AbstractBindingResult
import org.springframework.web.bind.annotation.*
import springfox.documentation.annotations.ApiIgnore
import java.time.LocalDateTime
import javax.validation.Valid

/**
 * @description 文件相关接口
 * @author sxt
 * @date 2021/3/25 2:07 下午
 * @version 1.0
 */
@RestController
@RequestMapping(FILE_PREFIX)
@Api(tags = ["文件相关接口"])
class FileController {

    @Autowired
    lateinit var fileService: FileService

    @Autowired
    lateinit var cosUtil: COSUtil

    companion object {
        const val FOLDER_PREFIX = "cshm/file"
    }

    @PostMapping
    @ApiOperation("文件上传")
    @ValidateAspect.ParamValidate
    fun addFiles(
        @Valid fileInfo: FileUploadParam,
        @ApiIgnore bindingResult: AbstractBindingResult
    ): ResultData<FileVO> {
        val toFile = MultipartFileToFile.multipartFileToFile(fileInfo.file)
        val folder = fileInfo.tag?.let { "$FOLDER_PREFIX/$it" } ?: "$FOLDER_PREFIX/default"
        val result =
            cosUtil.putFile(
                file = toFile,
                folder = folder,
                fileName = "${fileInfo.fileName}-${fileInfo.secondaryTag}-${UUIDUtils.getCode()}"
            )
        //删除临时文件
        MultipartFileToFile.deleteTempFile(toFile)

        // 保存文件上传结果
        var file = MappingUtil.getMappingObject(fileInfo, File::class.java)
        val url = result.second
        val relativePath = result.third

        val tmp = fileService.getOne(KtQueryWrapper(File::class.java).eq(File::secondaryTag, file.secondaryTag))
        file = tmp?.apply {
            fileRelativePath?.let { path -> if (path != relativePath) cosUtil.deleteFile(filePath = path) }
            fileFullPath = url
            fileRelativePath = relativePath
            this.folder = folder
            modifier = 0
            modifiedTime = LocalDateTime.now()
        }
            ?: file.apply {
                fileFullPath = url
                fileRelativePath = relativePath
                this.folder = folder
                creator = 0
                createdTime = LocalDateTime.now()
            }

        return if (fileService.saveOrUpdate(file))
            ResultData.SUCCESS(data = fileService.queryFileVOById(file.id!!))
        else {
            file.fileRelativePath?.let { path -> if (path != relativePath) cosUtil.deleteFile(filePath = path) }
            ResultData.FAILED(msg = "上传文件时发送未知异常", data = null)
        }
    }

    @GetMapping
    @ApiOperation("查询文件信息")
    fun getFiles(fileQueryParam: FileQueryParam): ResultData<PageDataVO<FileVO>> {
        return ResultData.SUCCESS(data = fileService.queryFiles(fileQueryParam))
    }

    @DeleteMapping
    @ApiOperation("删除文件信息")
    @ApiImplicitParam(name = "key", value = "id 或者 二级tag")
    fun removeFile(key: String): ResultData<Boolean> {
        val tmp = fileService.getOne(
            KtQueryWrapper(File::class.java)
                .eq(File::id, key)
                .or()
                .eq(File::secondaryTag, key)
        )
        tmp?.let {
            it.fileRelativePath?.let { path ->
                cosUtil.deleteFile(filePath = path)
            }
            it.del = IsDelEnum.YES.code
            it.modifier = 0
            it.modifiedTime = LocalDateTime.now()
            return if (fileService.updateById(it) && fileService.removeById(it))
                ResultData.SUCCESS("文件删除成功")
            else
                ResultData.FAILED("文件删除失败")
        }
            ?: return ResultData.FAILED("文件不存在")
    }

}
